<script setup>
import { onMounted, ref, computed, nextTick } from "vue";
import Voice from "./Voice.vue";
import { getChatMenuList, addChatMenu, list, start } from "../../services/chat";
import { useChatMenuIdStore } from "../../store/ChatMenuStore";
import { bus } from "../../mitt/mitt";
import MarkdownIt from "markdown-it";
import back from "../../assets/images/back.jpg";
import History from "./History.vue";
defineProps({});
//store
const chatMenuIdStore = useChatMenuIdStore();

//头像
const userImg = computed(() => {
  return JSON.parse(localStorage.getItem("userData")).headPic;
});

//菜单
const chatMenuList = ref();
const f_getChatMenuList = function () {
  chatMenuList.value = [];
  getChatMenuList({})
    .then((res) => {
      chatMenuList.value = res.data;
      if (res.data.length > 0) {
        chatMenuIdStore.setChatMenuId(res.data[0].id);
        chatInfo.value.chatMenuId = res.data[0].id;
        getChatContentList(res.data[0].id);
        const newdata = [];
        res.data.forEach((i) => {
          const newItem = {
            text: i.chatMenuName,
            value: i.id,
          };
          newdata.push(newItem);
        });
        columns.value = newdata;
      } else {
        chatMenuIdStore.setChatMenuId("");
      }
    })
    .catch((error) => {});
};
//内容
const chatId = ref();
const chatContentList = ref([]);
const markdown = new MarkdownIt();
const getChatContentList = function (id) {
  chatContentList.value = [];
  list(id)
    .then((res) => {
      res.data = res.data.filter((i) => i.contentType === 2);
      res.data.forEach((i) => {
        i.realContent = i.replyContent;
        i.replyContent = markdown.render(i.replyContent);
      });
      chatContentList.value = res.data;
      scrollToBottom();
    })
    .catch((error) => {});
};
//展示底部
const scrollContainer = ref(null);
const scrollToBottom = function () {
  nextTick(() => {
    scrollContainer.value.scrollTop = scrollContainer.value.scrollHeight;
  });
};

//语音结果
const result = ref("");
const voiceCallback = (text) => {
  result.value = text;
};
//聊天
const chatInfo = ref({
  question: result,
  chatMenuId: "",
  contentType: 2,
  prompt: "阳光明媚",
});
//发送按钮是否禁用
const isDisabled = ref(false);
const loading = ref(false);
//发送
const sendMsg = function () {
  if (chatInfo.value.question == "") {
    showNotify({ type: "danger", message: "聊天内容不为空" });
    return;
  } else {
    if (chatInfo.value.chatMenuId == "") {
      addChatMenu({
        chatMenuName:
          chatInfo.value.question.length > 20
            ? chatInfo.value.question.substring(0, 20)
            : chatInfo.value.question,
      })
        .then((res) => {
          bus.emit("addChatMenu", "");
          nextTick(() => {
            chatInfo.value.chatMenuId = res.data;
            sseWatch(res.data);
          });
        })
        .catch((error) => {});
    } else {
      sseWatch(chatInfo.value.chatMenuId);
    }
  }
};
//sse监听
const sseWatch = function (chatMenuId) {
  const id = Math.floor(Math.random() * 10000000) + "";
  chatId.value = id;
  const chatContent = ref({
    id: id,
    realContent: "",
    contentType: chatInfo.value.contentType,
    askContent: chatInfo.value.question,
    replyContent: (chatInfo.value.contentType == 1) | 2 ? "<br><br><br><br><br><br>" : "",
  });
  if (!!window.EventSource) {
   const chatUrl=  import.meta.env.VITE_CHAT_SSE
    var source = new EventSource(
      `${chatUrl}/addSse?id=${chatMenuId}`
    );
    source.onerror = (e) => {
      source.close();
      isDisabled.value = false;
      chatInfo.value.question = "";
    };
    //建立链接
    source.addEventListener("open", (e) => {});
    //监听开始消息
    source.addEventListener("start", (e) => {
      chatContentList.value.push(chatContent.value);
      loading.value = true;
      scrollToBottom();
      isDisabled.value = true;
      start(chatInfo.value)
        .then((res) => {})
        .catch((error) => {});
    });
    // 监听数据
    source.addEventListener("data", (e) => {
      loading.value = false;
      let sseData = JSON.parse(e.data);
      chatContent.value.realContent = sseData.text;
      chatContent.value.replyContent = markdown.render(sseData.text);
      scrollToBottom();
    });
    //监听后台err消息
    source.addEventListener("err", (e) => {
      loading.value = false;
      chatContent.value.realContent = e.data;
      chatContent.value.replyContent = markdown.render(e.data);
      scrollToBottom();
    });
  } else {
    console.log("你的浏览器不支持sse ");
  }
};
//历史记录
const columns = ref();
const historyMenuList = ref([]);
//清空菜单内容
const showPopover = ref(false);
const actions = [{ text: "清空内容" }, { text: "历史记录" }];
const isShowHistory = ref(false);
const checkSelect =  (action) => {
  if (action.text === "清空内容") {
    showConfirmDialog({
      message: "确定清空这段对话吗？",
    })
      .then(() => {
        chatInfo.value.chatMenuId = "";
        chatContentList.value = [];
      })
      .catch(() => {});
  } else if (action.text === "历史记录") {
    isShowHistory.value = true;
  }
};
const refreshChatContent = (id) => {
  chatInfo.value.chatMenuId = id;
  getChatContentList(id);
};
onMounted(() => {
  f_getChatMenuList();
});
</script>
<template>
  <div class="chat">
    <div class="top">
      <div class="top_left">
        <History
          v-model="isShowHistory"
          @refreshChatContent="refreshChatContent"
        ></History>
        <van-popover
          @select="checkSelect"
          v-model:show="showPopover"
          :actions="actions"
          placement="bottom-end"
        >
          <template #reference>
            <van-icon name="ellipsis" size="30" />
          </template>
        </van-popover>
      </div>
    </div>
    <div class="content" ref="scrollContainer">
      <div class="chat-content-item" v-for="item in chatContentList" :key="item.id">
        <div class="ask">
          <div class="ask-item">
            <div v-html="item.askContent" class="ask-item-item"></div>
          </div>
          <van-image
            round
            width="45"
            height="45"
            :src="
              userImg == null
                ? 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg'
                : userImg
            "
          />
        </div>
        <div class="reply">
          <van-image round width="45" height="45" :src="back" />
          <div class="reply-item">
            <div
              v-if="item.id == chatId"
              class="reply-item-item"
              v-html="item.replyContent"
              v-loading="loading"
              element-loading-text="加载中请稍等！！"
              v-highlight
            ></div>
            <div
              v-else
              class="reply-item-item"
              v-html="item.replyContent"
              v-highlight
            ></div>
          </div>
        </div>
      </div>
    </div>
    <div class="bottom">
      <Voice @voice-callback="voiceCallback"></Voice>

      <van-field
        v-model="result"
        center
        clearable
        class="bottom_input"
        placeholder="请输入要发送文本"
      >
      </van-field>
      <div class="bottom_botton">
        <van-button
          @click="sendMsg"
          size="small"
          type="primary"
          class="botton"
          :disabled="isDisabled"
          >发送</van-button
        >
      </div>
    </div>
  </div>
</template>

<style lang="less" scoped>
.chat {
  display: flex;
  height: 100%;
  flex-direction: column;
  .top {
    display: flex;
    justify-content: flex-end;
    flex-shrink: 0;
    height: 65px;
    border-radius: 8px;
    background-image: radial-gradient(circle, rgb(219, 251, 251), rgb(209, 223, 249));
    position: relative; /* 确保子元素不会覆盖背景 */
    .top_left {
      display: flex;
      align-items: center;
      margin-right: 10px;
    }
  }
  .content {
    flex: 1; /* 占据剩余空间 */
    overflow-y: auto; /* 如果内容过多，允许滚动 */
    background-color: rgb(244, 247, 252);
    .chat-content-item {
      .ask {
        margin-top: 15px;
        display: flex;
        justify-content: flex-end;
        /* 将内容靠右对齐 */
        .ask-item {
          margin-right: 5px;
          max-width: 80%;
          min-width: 15%;
          background-color: rgb(86, 130, 251);
          border-radius: 10px;
          .ask-item-item {
            margin-left: 10px;
            margin-right: 10px;
            color: #ffffff;
            font-size: 14px;
            line-height: 45px;
            text-align: center;
          }
        }
      }

      .reply {
        margin-top: 15px;
        display: flex;
        .reply-item {
          margin-left: 5px;
          background-color: #ffffff;
          width: 80%;
          overflow: auto;
          border-radius: 10px;
          .reply-item-item {
            margin-left: 10px;
            margin-right: 10px;
            font-size: 14px;
            line-height: 1.5;
          }

          :deep(img) {
            max-width: 100%;
          }

          :deep(pre code.hljs) {
            margin-top: 10px;
            margin-bottom: 10px;
            border-radius: 10px;
          }
        }
      }
    }
  }
  .bottom {
    margin-top: auto; /* pushes .bottom to the bottom */
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    height: 80px;
    .bottom_input {
      width: 50%;
      border-radius: 30px;
      background-color: rgb(241, 242, 247);
    }
    .bottom_botton {
      width: 20%;
      margin-left: 5%;
      margin-right: 5%;
      .botton {
        width: 100%;
        border-radius: 30px;
        height: 44px;
        background-color: rgb(113, 123, 150);
        border: 0px;
        font-size: 15px;
      }
    }
  }
}
</style>
